﻿using EventBus.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace EventBus.Simple
{
    public class PassThroughEventBus
        : IEventBus
    {
        private EventQueue _eventQueue = new EventQueue();
        private IEnumerable<IEventHandler> _eventHandlers;
        private IEventHandlerExecutionContext _executionContext;
        public PassThroughEventBus(IEnumerable<IEventHandler> eventHandlers, IEventHandlerExecutionContext executionContext)
        {
            _eventHandlers = eventHandlers;
            _executionContext = executionContext;
            _eventQueue.EventPushed += _eventQueue_EventPushed;
        }


        public Task PublishAsync<T>(T @event, CancellationToken cancellationToken = default(CancellationToken)) where T : IEvent
        {
            _eventQueue.Push(@event);
            return Task.CompletedTask;
        }



        private void _eventQueue_EventPushed(object sender, EventProcessedEventArgs e)
        {
            _eventHandlers.Where(ev => ev.CanHandle(e.Event))
                .ToList()
                .ForEach(ev =>
                {
                    ev.HandleAsync(e.Event).Wait();
                });
        }

        public void Dispose()
        {
            _eventQueue.EventPushed -= _eventQueue_EventPushed;
        }

        public void Subscribe<TEvent, TEventHandler>()
            where TEvent : IEvent
            where TEventHandler : IEventHandler<TEvent>
        {
            if (!_executionContext.HandlerRegistered(typeof(TEvent), typeof(TEventHandler)))
            {
                _executionContext.RegisterHandler<TEvent, TEventHandler>();
            }
        }
    }
}
